/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.bingluo.livewallpaper.hunterxhunter;

import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.os.Handler;
import android.os.SystemClock;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

/*
 * This animated wallpaper draws a rotating wireframe shape. It is similar to
 * example #1, but has a choice of 2 shapes, which are user selectable and
 * defined in resources instead of in code.
 */

public class MainWallpaperService extends WallpaperService {

	public static final String SHARED_PREFS_NAME = "hxh_settings";
	public static final String TAG = "MainWallpaperService";
	public static final int BG_TOTAL =6;

	static class ThreeDPoint {
		float x;
		float y;
		float z;
	}

	static class ThreeDLine {
		int startPoint;
		int endPoint;
	}

	@Override
	public void onCreate() {
		super.onCreate();
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
	}

	@Override
	public Engine onCreateEngine() {
		return new MainEngine();
	}

	class MainEngine extends Engine implements
			SharedPreferences.OnSharedPreferenceChangeListener {

		private final Handler mHandler = new Handler();

		ThreeDPoint[] mOriginalPoints;
		ThreeDPoint[] mRotatedPoints;
		ThreeDLine[] mLines;
		private final Paint mPaint = new Paint();
		private float mOffset;
		private float mTouchX = -1;
		private float mTouchY = -1;
		private long mStartTime;
		private float mCenterX;
		private float mCenterY;

		int[] mDefBgs;

		private final Runnable mDrawMain = new Runnable() {
			public void run() {
				drawFrame();
			}
		};
		private final Runnable mDrawDc = new Runnable() {
			public void run() {
				isChanging = true;
				do {
					mPaint.setAlpha(ALPHA_MAX);
					mPaint.setTypeface(Typeface.MONOSPACE);
					mPaint.setColor(Color.WHITE);
					drawFrame();
				} while (isFading);
				mHandler.removeCallbacks(mDrawDc);
				isChanging= false; 
			}
		};
		private boolean mVisible;
		private SharedPreferences mPrefs;

		private String fangxiang = "";

		private float cX = 0.0f;

		private Bitmap hxh_099;

		private int widthFrame;

		private int heighFrame;

		private int mXPixels = 0;

		private int mYPixels = 0;
		private int bgIndex = 0;

		private boolean is_boundary_change_bg;

		private boolean is_auto_change_bg;

		private int auto_change_bg_time;

		private int cBgWidth;

		private long logTime;

		private boolean isChanging;

		private String direction;

		private Bitmap cBmp;

		private float startTouchX;

		private float endTouchX;

		private int moveCount;

		private int select_bg_settings;

		private boolean on_off_select_bg_settings;

		MainEngine() {
			// Create a Paint to draw the lines for our cube
			final Paint paint = mPaint;
			paint.setColor(0xffffffff);
			paint.setAntiAlias(true);
			paint.setStrokeWidth(2);
			paint.setStrokeCap(Paint.Cap.ROUND);
			paint.setStyle(Paint.Style.STROKE);
			
			isChanging = false;
			direction = "-";
			select_bg_settings = 0;
			
			mDefBgs = new int[BG_TOTAL];
			//默认第0个
			bgIndex = 0;

			mDefBgs[0] = R.drawable.hxh_0;
			mDefBgs[1] = R.drawable.hxh_1;
			mDefBgs[2] = R.drawable.hxh_2;
			mDefBgs[3] = R.drawable.hxh_3;
			mDefBgs[4] = R.drawable.hxh_4;
			mDefBgs[5] = R.drawable.hxh_5;
			
			cBmp = BitmapFactory.decodeResource(getResources(), mDefBgs[bgIndex]);
			cBgWidth = cBmp.getWidth();
			
//			hxh_0 = Bitmap.createBitmap(hxh_099.getWidth(), hxh_099.getHeight(), Bitmap.Config.RGB_565);
//			Log.d(TAG, "hxh_0.getWidth()=="+hxh_0.getWidth());
			mStartTime = SystemClock.elapsedRealtime();
			logTime = System.currentTimeMillis();

			mPrefs = MainWallpaperService.this.getSharedPreferences(
					SHARED_PREFS_NAME, 0);
			mPrefs.registerOnSharedPreferenceChangeListener(this);
			onSharedPreferenceChanged(mPrefs, null);
		}

		public void onSharedPreferenceChanged(SharedPreferences prefs,
				String key) {

			Log.d(TAG, "----------------------------");
			String shape = prefs.getString("cube2_shape", "cube");
			//打开设置背景
			on_off_select_bg_settings = prefs.getBoolean("on_off_select_bg_settings", false);
			//固定的背景
			select_bg_settings = Integer.valueOf(prefs.getString("select_bg_settings", "1"));
			//是否边界换图
			is_boundary_change_bg = prefs.getBoolean("edge_auto_change_bg", false);
			
			//是否自动换图
			is_auto_change_bg = prefs.getBoolean("auto_change_bg", false);
			//自动换图时间
			auto_change_bg_time = Integer.valueOf(prefs.getString("auto_change_bg_time", "10"));
			
			Log.d(TAG, "on_off_select_bg_settings="+on_off_select_bg_settings);
			Log.d(TAG, "select_bg_settings="+select_bg_settings);
			Log.d(TAG, "is_boundary_change_bg="+is_boundary_change_bg);
			Log.d(TAG, "is_auto_change_bg="+is_auto_change_bg);
			Log.d(TAG, "auto_change_bg_time="+auto_change_bg_time);
			Log.d(TAG, "----------------------------");
			
			if (on_off_select_bg_settings) {
				bgIndex = select_bg_settings - 1;
				cBmp = BitmapFactory.decodeResource(getResources(), mDefBgs[bgIndex]);
				cBgWidth = cBmp.getWidth();
			}

			// read the 3D model from the resource
			// readModel(shape);
//			if (is_auto_change_bg) {
//				new Thread(){
//
//					@Override
//					public void run() {
//						// TODO Auto-generated method stub
//						super.run();
//						while (is_auto_change_bg && select_bg_settings == 0) {
//							try {
//								sleep(auto_change_bg_time*1000);
//								Log.d(TAG, "auto_change_bg_time="+auto_change_bg_time);
//								changeBg();
//							} catch (InterruptedException e) {
//								// TODO Auto-generated catch block
//								e.printStackTrace();
//							}
//						}
//					}
//					
//				}.start();
//			}
		}

		private void readModel(String prefix) {
			// Read the model definition in from a resource.

			// get the resource identifiers for the arrays for the selected
			// shape
			int pid = getResources().getIdentifier(prefix + "points", "array",
					getPackageName());
			int lid = getResources().getIdentifier(prefix + "lines", "array",
					getPackageName());

			String[] p = getResources().getStringArray(pid);
			int numpoints = p.length;
			mOriginalPoints = new ThreeDPoint[numpoints];
			mRotatedPoints = new ThreeDPoint[numpoints];

			for (int i = 0; i < numpoints; i++) {
				mOriginalPoints[i] = new ThreeDPoint();
				mRotatedPoints[i] = new ThreeDPoint();
				String[] coord = p[i].split(" ");
				mOriginalPoints[i].x = Float.valueOf(coord[0]);
				mOriginalPoints[i].y = Float.valueOf(coord[1]);
				mOriginalPoints[i].z = Float.valueOf(coord[2]);
			}

			String[] l = getResources().getStringArray(lid);
			int numlines = l.length;
			mLines = new ThreeDLine[numlines];

			for (int i = 0; i < numlines; i++) {
				mLines[i] = new ThreeDLine();
				String[] idx = l[i].split(" ");
				mLines[i].startPoint = Integer.valueOf(idx[0]);
				mLines[i].endPoint = Integer.valueOf(idx[1]);
			}
		}

		@Override
		public void onCreate(SurfaceHolder surfaceHolder) {
			super.onCreate(surfaceHolder);
			setTouchEventsEnabled(true);
		}

		@Override
		public void onDestroy() {
			super.onDestroy();
			mHandler.removeCallbacks(mDrawMain);
		}

		@Override
		public void onVisibilityChanged(boolean visible) {
			mVisible = visible;
			if (visible) {
				drawFrame();
			} else {
				mHandler.removeCallbacks(mDrawMain);
			}
		}

		@Override
		public void onSurfaceChanged(SurfaceHolder holder, int format,
				int width, int height) {
			super.onSurfaceChanged(holder, format, width, height);
			// store the center of the surface, so we can draw the cube in the
			// right spot
			mCenterX = width / 2.0f;
			mCenterY = height / 2.0f;
			drawFrame();
		}

		@Override
		public void onSurfaceCreated(SurfaceHolder holder) {
			super.onSurfaceCreated(holder);
		}

		@Override
		public void onSurfaceDestroyed(SurfaceHolder holder) {
			super.onSurfaceDestroyed(holder);
			mVisible = false;
			mHandler.removeCallbacks(mDrawMain);
		}

		@Override
		public void onOffsetsChanged(float xOffset, float yOffset, float xStep,
				float yStep, int xPixels, int yPixels) {
			
			mOffset = xOffset;
			mXPixels = xPixels;
			mYPixels = yPixels;
			
			drawFrame();
//			Log.d(TAG, "xOffset=" + xOffset + "::yOffset=" + yOffset
//					+ "::xStep=" + xStep + "::yStep=" + yStep + "::xPixels="
//					+ xPixels + "::yPixels=" + yPixels);
		}

		/*
		 * Store the position of the touch event so we can use it for drawing
		 * later
		 */
		@Override
		public void onTouchEvent(MotionEvent event) {
//			if (event.getAction() == MotionEvent.ACTION_MOVE) {
//				Log.d(TAG, "mTouchX=="+mTouchX);
//				Log.d(TAG, "(event.getX())=="+event.getX());
//				Float lastTouchX = mTouchX;
//				String cDirection = direction;
//				Boolean isXD = (mTouchX == event.getX());
//				if (mTouchX > event.getX()) {
//					direction  = "-";
//				} else {
//					direction = "+";
//				}
//				mTouchX = event.getX();
//				mTouchY = event.getY();
////				long now = System.currentTimeMillis();
////				long tmp = now-logTime;
////				logTime = now;
//				Log.d(TAG, "(direction:cDirection)=="+direction+":"+cDirection);
//				Log.d(TAG, "lastTouchX > -1.0f=="+":"+(lastTouchX > -1.0f));
//				if (cDirection == direction && lastTouchX > -1.0f && !isXD && (mOffset == 0.0f || mOffset == 1.0f)) {
//					if (!isChanging) {
//						isChanging = true;
//						//边界换图
//						if (is_boundary_change_bg) {
//	//						bgIndex = new Random().nextInt(3)%(3-0+1) + 0;
//							bgIndex = (bgIndex+1)%4;
//							cBmp = BitmapFactory.decodeResource(getResources(), mDefBgs[bgIndex]);
//							cBgWidth = cBmp.getWidth();
//							configFadeAction(1500, ALPHA_MAX, ALPHA_MIN, UPDATE_TIME);
//							mHandler.postDelayed(mDrawDc, 100);
//						}
//					}
//				}
//			} else {
//				mTouchX = -1;
//				mTouchY = -1;
//			}
			
			Log.d(TAG, "moveCount="+moveCount);
			if (event.getAction() == MotionEvent.ACTION_DOWN) {
				startTouchX = event.getX();
				Log.d(TAG, "ACTION_DOWN@"+startTouchX);
			} else if (event.getAction() == MotionEvent.ACTION_UP) {
				endTouchX = event.getX();
				Log.d(TAG, "ACTION_UP@"+endTouchX);
				if (moveCount>=2) {
					moveCount = 0;
					if ((mOffset == 0.0f || mOffset == 1.0f)) {
						Log.d(TAG, "边界换图"+is_boundary_change_bg);
						changeBg();
					}
				}
			} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
				moveCount++;
			} else {
				mTouchX = -1;
				mTouchY = -1;
			}
			
			super.onTouchEvent(event);
		}

		private synchronized void changeBg() {
			if (on_off_select_bg_settings) {
				return;
			}
			Log.d(TAG, "changeBg::isChanging=="+isChanging+"::is_boundary_change_bg="+is_boundary_change_bg);
			if (!isChanging) {
				//边界换图
				if (is_boundary_change_bg) {
//						bgIndex = new Random().nextInt(3)%(3-0+1) + 0;
					bgIndex = (bgIndex+1)%(BG_TOTAL);
					cBmp = BitmapFactory.decodeResource(getResources(), mDefBgs[bgIndex]);
					cBgWidth = cBmp.getWidth();
					configFadeAction(1500, ALPHA_MAX, ALPHA_MIN, UPDATE_TIME);
					mHandler.postDelayed(mDrawDc, 100);
				}
			}
		}
		
		private static final int UPDATE_TIME = 50;
		// Alpha极值
		protected static final int ALPHA_MIN = 0;
		protected static final int ALPHA_MAX = 255;

		// 特效执行标志
		protected boolean isFading = false;

		// 起始透明度
		private int alphaFrom;

		// 终了透明度
		private int alphaTo;

		// 特效持续时间(毫秒)
		private int duration;

		// 刷新间隔时间(毫秒)
		private int updateTime;

		// 透明度变化梯度
		private int alphaStep;

		// 特效执行时间
		private int fadeTime;

		// 当前透明度
		private int fadeAlpha;
		
		/**
		 * 配置特效参数
		 */
		public void configFadeAction(int _duration, int _alphaFrom, int _alphaTo, int _updateTime) {
			duration = _duration;
			alphaFrom = _alphaFrom;
			alphaTo = _alphaTo;
			updateTime = _updateTime;

			fadeTime = 0;
			fadeAlpha = alphaFrom;
			alphaStep = (alphaTo - alphaFrom) / (duration / updateTime);
//			Log.d(TAG, "alphaStep=="+alphaStep);

			isFading = true;
		}
		
		/**
		 * 执行特效
		 * @param canvas 
		 * @param paint
		 */
		public void confirmFadeAction(Canvas canvas, Paint paint) {
			try {
				fadeAlpha += alphaStep;
//				Log.d(TAG, "fadeAlpha=="+fadeAlpha);

				paint.setAlpha(fadeAlpha);
//				canvas.drawPaint(paint);

				fadeTime += updateTime;
			} catch(Exception e) {
				Log.e(e.getClass().getName(), e.getMessage());
				isFading = false;
			} finally {
				if(fadeTime > duration) {
					isFading = false;
				}
			}
		}

		/*
		 * Draw one frame of the animation. This method gets called repeatedly
		 * by posting a delayed Runnable. You can do any drawing you want in
		 * here. This example draws a wireframe cube.
		 */
		synchronized void drawFrame() {
			final SurfaceHolder holder = getSurfaceHolder();
			final Rect frame = holder.getSurfaceFrame();
			widthFrame = frame.width();
			heighFrame = frame.height();

			Canvas c = null;
			try {
				c = holder.lockCanvas();
				if (c != null) {
					// draw something
					drawMain(c);
					drawTouchPoint(c);
				}
			} finally {
				if (c != null)
					holder.unlockCanvasAndPost(c);
			}

//			mHandler.removeCallbacks(mDrawMain);
			if (mVisible) {
//				mHandler.postDelayed(mDrawMain, 1000 / 25);
			}
		}

		private void drawMain(Canvas c) {
			// TODO Auto-generated method stub
			c.save();
			c.translate(0, 0);
			c.drawColor(0xff000000);
			
			cX = 0.0f-(cBgWidth-widthFrame)*mOffset;
//			Log.d(TAG, "cBgWidth=="+cBgWidth);
//			Log.d(TAG, "widthFrame=="+widthFrame);
//			Log.d(TAG, "mOffset=="+mOffset);
//			Log.d(TAG, "cX=="+cX);
//			if (cX == widthFrame && mOffset == 0.0f) {
//				cX = 0.0f;
//			} else if (cX < widthFrame && cX > 0.0f) {
//				cX = 0.0f - cX;
//			}
			
//			Bitmap bmp = BitmapFactory.decodeResource(getResources(), mDefBgs[bgIndex]);
			if(!isFading) {
				c.drawBitmap(cBmp, cX, 0, null);
//				Log.d(TAG, "---------");
			} else {
				c.drawBitmap(cBmp, cX, 0, mPaint);
				confirmFadeAction(c, mPaint);
//				Log.d(TAG, "-++++++++++++++==");
				c.drawPaint(mPaint);
			}
			
			c.restore();
		}

		void drawTouchPoint(Canvas c) {
			if (mTouchX >= 0 && mTouchY >= 0) {
//				Log.d(TAG, "----drawTouchPoint");
				// c.drawCircle(mTouchX, mTouchY, 80, mPaint);
			}
		}
	}
}
